/*!	 mutex.h
**	 Template Header
**
**	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
**
**	This package is free software; you can redistribute it and/or
**	modify it under the terms of the GNU General Public License as
**	published by the Free Software Foundation; either version 2 of
**	the License, or (at your option) any later version.
**
**	This package is distributed in the hope that it will be useful,
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**	General Public License for more details.
**
*/

#ifndef __SYNFIG_MUTEX_H
#define __SYNFIG_MUTEX_H

namespace synfig
{

class RecMutex;

class Mutex
{
    friend class RecMutex;

protected:
    void* blackbox;

public:

    class Lock
    {
        Mutex& mutex;
    public:
        Lock(Mutex& x): mutex(x)
        {
            mutex.lock();
        }
        ~Lock()
        {
            mutex.unlock();
        }
    };

    Mutex();
    ~Mutex();

    void lock();
    void unlock();
    bool try_lock();
    bool is_locked();

private:
    // Non-copyable
    Mutex(const Mutex&);

    // Non-assignable
    void operator=(const Mutex&);
};

class RecMutex : public Mutex
{
public:
    RecMutex();

    void unlock_all();
};

class RWLock
{
    void* blackbox;

public:

    class ReaderLock
    {
        RWLock& rw_lock;
    public:
        ReaderLock(RWLock& x): rw_lock(x)
        {
            rw_lock.reader_lock();
        }
        ~ReaderLock()
        {
            rw_lock.reader_unlock();
        }
    };
    class WriterLock
    {
        RWLock& rw_lock;
    public:
        WriterLock(RWLock& x): rw_lock(x)
        {
            rw_lock.writer_lock();
        }
        ~WriterLock()
        {
            rw_lock.writer_unlock();
        }
    };

    RWLock();
    ~RWLock();

    void reader_lock();
    void reader_unlock();
    bool reader_trylock();

    void writer_lock();
    void writer_unlock();
    bool writer_trylock();
};

}; // END of namespace synfig

#endif